﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using IBatisNet.Common;
using IBatisNet.Common.Utilities;
using IBatisNet.DataMapper.Configuration.Statements;
using IBatisNet.DataMapper.MappedStatements;
using IBatisNet.DataMapper;
using IBatisNet.DataMapper.Scope;
using System.Collections;
using IBatisNet.DataMapper.Configuration;

namespace Kaiser.Repositories.iBatis
{

    /// <summary>
    /// IBatis 使用工具类
    /// </summary>
    public class BatisHepler : Kaiser.Repositories.iBatis.IBatisHepler
    {
        private ISqlMapper mapper = null;
        public BatisHepler(string mappath)
        {
            //Resources.GetResourceAsXmlDocument("CMSMap.xml");
            DomSqlMapBuilder builder = new DomSqlMapBuilder();//其作用是根据配置文件创建SqlMap实例。
            mapper = builder.Configure("Configs/" + mappath) as SqlMapper;//SqlMapper是iBatisNet的核心组件，提供数据库操作的基础平台。SqlMapper可通过DomSqlMapBuilder创建。

        }

        /// <summary>
        /// 执行添加操作
        /// </summary>
        /// <param name="tag">语句ID</param>
        /// <param name="paramObject">语句所需要的参数</param>
        /// <returns>添加的主键</returns>
        public object ExcuteInsert(string tag, Object paramObject)
        {
            return mapper.Insert(tag, paramObject);
        }


        /// <summary>
        /// 执行删除操作
        /// </summary>
        /// <param name="tag">语句ID</param>
        /// <param name="paramObject">语句所需要的参数</param>
        /// <returns>影响行数</returns>
        public int ExcuteDelete(string tag, object paramObject)
        {
            return mapper.Delete(tag, paramObject);
        }
        /// <summary>
        /// 执行修改操作
        /// </summary>
        /// <param name="tag">语句ID</param>
        /// <param name="paramObject">语句所需要的参数</param>
        /// <returns>影响行数</returns>
        public int ExcuteUpdate(string tag, Object paramObject)
        {
            return mapper.Update(tag, paramObject);
        }
        /// <summary>
        /// 查询单个实体对象
        /// </summary>
        /// <param name="tag">语句ID</param>
        /// <param name="paramObject">语句所需要的参数</param>
        /// <returns>得到的Object</returns>
        public object ExcuteSelectObj(string tag, object paramObject)
        {
            object obj = mapper.QueryForObject(tag, paramObject);
            return obj;
        }
        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="tag">语句ID</param>
        /// <param name="paramObject">语句所需要的参数</param>
        /// <param name="pageIndex">页索引</param>
        /// <param name="pageSize">每页显示的记录数</param>
        /// <returns>得到的List集合</returns>
        public IList ExcuteSelect(string tag, object paramObject, int pageIndex, int pageSize)
        {
            return mapper.QueryForList(tag, paramObject, pageIndex, pageSize);
        }


        /// <summary>
        /// 通用的以DataTable的方式得到Select的结果(xml文件中参数要使用$标记的占位参数)
        /// </summary>
        /// <param name="tag">语句ID</param>
        /// <param name="paramObject">语句所需要的参数</param>
        /// <returns>得到的DataTable</returns>
        public DataTable ExcuteSelect(string tag, object paramObject)
        {
            DataSet ds = new DataSet();
            bool isSessionLocal = false;
            ISqlMapSession session = mapper.LocalSession;
            if (session == null)
            {
                session = mapper.CreateSqlMapSession();
                session.OpenConnection();
                isSessionLocal = true;
            }
            try
            {
                IDbCommand cmd = session.CreateCommand(CommandType.Text);
                cmd.Connection = session.Connection;
                cmd.CommandText = GetSql(tag, paramObject);
                IDbDataAdapter adapter = session.CreateDataAdapter(cmd);
                adapter.Fill(ds);
            }
            finally
            {
                if (isSessionLocal)
                {
                    session.CloseConnection();
                }
            }
            return ds.Tables[0];
        }
        public IList ExcuteSelectForPage(string tag, object paramObject, int pageIndex, int pageSize, ref int totalCount)
        {

            return mapper.QueryForList(tag, paramObject, pageIndex, pageSize);
        }

        /// <summary>
        /// 得到参数化后的SQL
        /// </summary>
        /// <param name="tag">语句ID</param>
        /// <param name="paramObject">语句所需要的参数</param>
        /// <returns>sql语句</returns>
        protected string GetSql(string tag, object paramObject)
        {
            IStatement statement = mapper.GetMappedStatement(tag).Statement;
            IMappedStatement mapStatement = mapper.GetMappedStatement(tag);
            ISqlMapSession session = mapper.CreateSqlMapSession();
            RequestScope request = statement.Sql.GetRequestScope(mapStatement, paramObject, session);
            return request.PreparedStatement.PreparedSql;
        }

        public IList<T> ExcuteSelectForList<T>(string tag, object paramObject, int PageSize, int curPage,
                                               out int recCount)
        {

            IDataReader dr = null;
            bool isSessionLocal = false;
            string sql = GetSql(tag, paramObject);

            var tcountsql = sql.Substring(sql.ToLower().IndexOf("from", System.StringComparison.Ordinal));

            var idx = tcountsql.IndexOf("order by", System.StringComparison.Ordinal);
            if (idx != -1)
            {
                tcountsql = tcountsql.Remove(idx);
            }

            string strCount = "select count(*) " + tcountsql;
            IDalSession session = mapper.LocalSession;
            var dt = new DataTable();
            if (session == null)
            {
                session = mapper.CreateSqlMapSession();
                session.OpenConnection();
                isSessionLocal = true;
            }
            try
            {
                IDbCommand cmdCount = session.CreateCommand(CommandType.Text);
                cmdCount.Connection = session.Connection;
                cmdCount.CommandText = strCount;
                object count = cmdCount.ExecuteScalar();
                recCount = Convert.ToInt32(count);

                return mapper.QueryForList<T>(tag, paramObject, curPage, PageSize);
            }
            finally
            {
                if (isSessionLocal)
                {
                    session.CloseConnection();
                }
            }

        }

        /// <summary>
        /// 用于分页控件使用
        /// </summary>
        /// <param name="tag">语句ID</param>
        /// <param name="paramObject">语句所需要的参数</param>
        /// <param name="PageSize">每页显示数目</param>
        /// <param name="curPage">当前页</param>
        /// <param name="recCount">记录总数</param>
        /// <returns>得到的DataTable</returns>
        public DataTable ExcuteSelect(string tag, object paramObject, int PageSize, int curPage, out int recCount)
        {
            IDataReader dr = null;
            bool isSessionLocal = false;
            string sql = GetSql(tag, paramObject);

            var tcountsql = sql.Substring(sql.ToLower().IndexOf("from", System.StringComparison.Ordinal));

            var idx = tcountsql.IndexOf("order by", System.StringComparison.Ordinal);
            if (idx != -1)
            {
                tcountsql = tcountsql.Remove(idx);
            }

            string strCount = "select count(*) " + tcountsql;
            IDalSession session = mapper.LocalSession;
            var dt = new DataTable();
            if (session == null)
            {
                session = mapper.CreateSqlMapSession();
                session.OpenConnection();
                isSessionLocal = true;
            }
            try
            {
                IDbCommand cmdCount = session.CreateCommand(CommandType.Text);
                cmdCount.Connection = session.Connection;
                cmdCount.CommandText = strCount;
                object count = cmdCount.ExecuteScalar();
                recCount = Convert.ToInt32(count);
                IDbCommand cmd = session.CreateCommand(CommandType.Text);
                cmd.Connection = session.Connection;
                cmd.CommandText = sql;
                dr = cmd.ExecuteReader();
                dt = Paging(dr, PageSize, curPage);
            }
            finally
            {
                if (isSessionLocal)
                {
                    session.CloseConnection();
                }
            }
            return dt;
        }

        /**/
        /// <summary>
        /// 取回合适数量的数据
        /// </summary>
        /// <param name="dataReader"></param>
        /// <param name="PageSize"></param>
        /// <param name="curPage"></param>
        /// <returns></returns>
        protected DataTable Paging(IDataReader dataReader, int PageSize, int curPage)
        {
            DataTable dt;
            dt = new DataTable();
            int colCount = dataReader.FieldCount;
            for (int i = 0; i < colCount; i++)
            {
                dt.Columns.Add(new DataColumn(dataReader.GetName(i), dataReader.GetFieldType(i)));
            }
            // 读取数据。将DataReader中的数据读取到DataTable中
            object[] vald = new object[colCount];
            int iCount = 0; // 临时记录变量
            while (dataReader.Read())
            {
                // 当前记录在当前页记录范围内
                if (iCount >= PageSize * (curPage - 1) && iCount < PageSize * curPage)
                {
                    for (int i = 0; i < colCount; i++)
                        vald[i] = dataReader.GetValue(i);
                    dt.Rows.Add(vald);
                }
                else if (iCount > PageSize * curPage)
                {
                    break;
                }
                iCount++; // 临时记录变量递增
            }
            if (!dataReader.IsClosed)
            {
                dataReader.Close();
                dataReader.Dispose();
            }
            return dt;
        }


        public IList ExcuteSelectForList(string tag, object paramObject)
        {
            return mapper.QueryForList(tag, paramObject);
        }

        public IList<T> ExcuteSelectForList<T>(string tag, object paramObject)
        {
            return mapper.QueryForList<T>(tag, paramObject);
        }
    }
}
